const Koa = require("Koa") // 导入Koa
const app = new Koa() // 创建对象
const cors = require("koa2-cors")
const static = require("koa-static")
const { userAgent } = require("koa-useragent") // 解析User-Agent 用户信息
const net = require("net") // 用于检查端口是否被占用

// 设置静态文件服务，例如图片存放在public文件夹下
app.use(static(__dirname + "/uploads"))

// 获取本机地址作为服务器地址
const os = require("os")
const networkInterfaces = os.networkInterfaces()

const localIP = getLocalIP()

global.port = 3000
// global.host = localIP
global.host = "localhost"

// 检测端口是否占用
const isPortFree = (port) =>
    new Promise((resolve) => {
        const tester = net
            .createServer()
            .once("error", (err) => {
                if (err.code === "EADDRINUSE") resolve(false)
                else resolve(false) // 其他错误也视为不可用
            })
            .once("listening", () => {
                tester.close(() => resolve(true))
            })
            .listen(port)
    })
// 自动获取可用端口
const getAvailablePort = async (startPort = 3000) => {
    let port = startPort
    let isFree = await isPortFree(port)
    while (!isFree) {
        console.log(`端口 ${port} 被占用，尝试 ${port + 1}`)
        port++
    }
    return port
}

const requireDirectory = require("require-directory") // 自动挂载路由
const Router = require("koa-router") // 路由

// 确保使用了解析请求体的中间件(没有这个 拿不到前端请求参数)
const bodyParser = require("koa-bodyparser")
app.use(bodyParser())
app.use(userAgent)

app.use(
    cors({
        origin: function (ctx) {
            // 在这里可以根据需要设置允许跨域的域名，或者使用函数来动态判断
            return "*" // 允许所有域名跨域请求，或者设置为具体的域名
        },
        maxAge: 5, // 表示在5秒内不需要再发送预检请求
        credentials: true, // 表示允许跨域请求发送cookies
        allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"], // 允许的请求方法
        allowHeaders: ["Content-Type", "Authorization", "Accept", "token"], // 允许的请求头
    })
)

// 路由拆分，可以用其他中间件拆分，更优雅(暂时先不优化，便于查找)
// const test = require('./route/test') // test测试  api
// const user = require('./route/user') // user用户  api

// app.use(test.routes())
// app.use(user.routes())

// 自动挂载路由
const apiDirectory = `${process.cwd()}/route`
requireDirectory(module, apiDirectory, { visit: whenModuleLoad })

// 挂载路由
function whenModuleLoad(obj) {
    if (obj instanceof Router) {
        app.use(obj.routes())
    } else if (typeof obj === "object") {
        // 兼容 module.exports 导出对象的写法
        for (let k in obj) {
            if (obj[k] instanceof Router) {
                app.use(obj[k].routes())
            }
        }
    }
}

// 启动Koa应用
const startServer = async () => {
    const port = await getAvailablePort(global.port) // 获取可用端口
    app.listen(port, global.host, () => console.log("服务端启动:" + host + ":" + port))
}
startServer().catch(console.error)

function getLocalIP() {
    for (const iface of Object.values(networkInterfaces)) {
        for (const config of iface) {
            if (config.family === "IPv4" && !config.internal) {
                return config.address
            }
        }
    }
    throw new Error("No IPv4 local IP address found")
}
